#include "Avalon/Threading/AsyncTaskQueue.hpp"
#include <boost/function.hpp>
#include "Avalon/Base/Algorithm.hpp"
#include "Avalon/Threading/ThreadPool.hpp"

using namespace Avalon;
using namespace Avalon::Threading;
using namespace boost;
using namespace std;

AsyncTaskQueue::AsyncTaskQueue() {}

AsyncTaskQueue::AsyncTaskQueue(ThreadPool& threadPool)
    : m_threadPool(&threadPool) {}

AsyncTaskQueue::~AsyncTaskQueue() {}

void AsyncTaskQueue::Initialize(ThreadPool& threadPool) {
  m_threadPool = &threadPool;
}

void AsyncTaskQueue::AddTask(const function<void ()>& operation) {
  m_pendingTasks.push_back(operation);
}

void AsyncTaskQueue::StartNextTask(Out<Async<void> > result) {
  function<void ()> task = m_pendingTasks.front();
  m_pendingTasks.pop_front();
  m_threadPool->Queue(task, Store(result));
  m_runningTasks.push_back(result.Get());
}

void AsyncTaskQueue::MarkTaskAsFinished(const Async<void>* result) {
  Remove(m_runningTasks, result);
}

int AsyncTaskQueue::GetPendingTaskCount() const {
  return static_cast<int>(m_pendingTasks.size());
}

int AsyncTaskQueue::GetRunningTaskCount() const {
  return static_cast<int>(m_runningTasks.size());
}

bool AsyncTaskQueue::IsEmpty() const {
  return GetPendingTaskCount() == 0 && GetRunningTaskCount() == 0;
}
